001 /* 002 * Copyright 2001-2005 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time; 017 018 import java.io.Serializable; 019 020 /** 021 * Identifies a field, such as year or minuteOfHour, in a chronology-neutral way. 022 * <p> 023 * A field type defines the type of the field, such as hourOfDay. 024 * If does not directly enable any calculations, however it does provide a 025 * {@link #getField(Chronology)} method that returns the actual calculation engine 026 * for a particular chronology. 027 * It also provides access to the related {@link DurationFieldType}s. 028 * <p> 029 * Instances of <code>DateTimeFieldType</code> are singletons. 030 * They can be compared using <code>==</code>. 031 * <p> 032 * If required, you can create your own field, for example a quarterOfYear. 033 * You must create a subclass of <code>DateTimeFieldType</code> that defines the field type. 034 * This class returns the actual calculation engine from {@link #getField(Chronology)}. 035 * 036 * @author Stephen Colebourne 037 * @author Brian S O'Neill 038 * @since 1.0 039 */ 040 public abstract class DateTimeFieldType implements Serializable { 041 042 /** Serialization version */ 043 private static final long serialVersionUID = -42615285973990L; 044 045 /** Ordinal values for standard field types. */ 046 static final byte 047 ERA = 1, 048 YEAR_OF_ERA = 2, 049 CENTURY_OF_ERA = 3, 050 YEAR_OF_CENTURY = 4, 051 YEAR = 5, 052 DAY_OF_YEAR = 6, 053 MONTH_OF_YEAR = 7, 054 DAY_OF_MONTH = 8, 055 WEEKYEAR_OF_CENTURY = 9, 056 WEEKYEAR = 10, 057 WEEK_OF_WEEKYEAR = 11, 058 DAY_OF_WEEK = 12, 059 HALFDAY_OF_DAY = 13, 060 HOUR_OF_HALFDAY = 14, 061 CLOCKHOUR_OF_HALFDAY = 15, 062 CLOCKHOUR_OF_DAY = 16, 063 HOUR_OF_DAY = 17, 064 MINUTE_OF_DAY = 18, 065 MINUTE_OF_HOUR = 19, 066 SECOND_OF_DAY = 20, 067 SECOND_OF_MINUTE = 21, 068 MILLIS_OF_DAY = 22, 069 MILLIS_OF_SECOND = 23; 070 071 /** The era field type. */ 072 private static final DateTimeFieldType ERA_TYPE = new StandardDateTimeFieldType( 073 "era", ERA, DurationFieldType.eras(), null); 074 /** The yearOfEra field type. */ 075 private static final DateTimeFieldType YEAR_OF_ERA_TYPE = new StandardDateTimeFieldType( 076 "yearOfEra", YEAR_OF_ERA, DurationFieldType.years(), DurationFieldType.eras()); 077 /** The centuryOfEra field type. */ 078 private static final DateTimeFieldType CENTURY_OF_ERA_TYPE = new StandardDateTimeFieldType( 079 "centuryOfEra", CENTURY_OF_ERA, DurationFieldType.centuries(), DurationFieldType.eras()); 080 /** The yearOfCentury field type. */ 081 private static final DateTimeFieldType YEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType( 082 "yearOfCentury", YEAR_OF_CENTURY, DurationFieldType.years(), DurationFieldType.centuries()); 083 /** The year field type. */ 084 private static final DateTimeFieldType YEAR_TYPE = new StandardDateTimeFieldType( 085 "year", YEAR, DurationFieldType.years(), null); 086 /** The dayOfYear field type. */ 087 private static final DateTimeFieldType DAY_OF_YEAR_TYPE = new StandardDateTimeFieldType( 088 "dayOfYear", DAY_OF_YEAR, DurationFieldType.days(), DurationFieldType.years()); 089 /** The monthOfYear field type. */ 090 private static final DateTimeFieldType MONTH_OF_YEAR_TYPE = new StandardDateTimeFieldType( 091 "monthOfYear", MONTH_OF_YEAR, DurationFieldType.months(), DurationFieldType.years()); 092 /** The dayOfMonth field type. */ 093 private static final DateTimeFieldType DAY_OF_MONTH_TYPE = new StandardDateTimeFieldType( 094 "dayOfMonth", DAY_OF_MONTH, DurationFieldType.days(), DurationFieldType.months()); 095 /** The weekyearOfCentury field type. */ 096 private static final DateTimeFieldType WEEKYEAR_OF_CENTURY_TYPE = new StandardDateTimeFieldType( 097 "weekyearOfCentury", WEEKYEAR_OF_CENTURY, DurationFieldType.weekyears(), DurationFieldType.centuries()); 098 /** The weekyear field type. */ 099 private static final DateTimeFieldType WEEKYEAR_TYPE = new StandardDateTimeFieldType( 100 "weekyear", WEEKYEAR, DurationFieldType.weekyears(), null); 101 /** The weekOfWeekyear field type. */ 102 private static final DateTimeFieldType WEEK_OF_WEEKYEAR_TYPE = new StandardDateTimeFieldType( 103 "weekOfWeekyear", WEEK_OF_WEEKYEAR, DurationFieldType.weeks(), DurationFieldType.weekyears()); 104 /** The dayOfWeek field type. */ 105 private static final DateTimeFieldType DAY_OF_WEEK_TYPE = new StandardDateTimeFieldType( 106 "dayOfWeek", DAY_OF_WEEK, DurationFieldType.days(), DurationFieldType.weeks()); 107 108 /** The halfday field type. */ 109 private static final DateTimeFieldType HALFDAY_OF_DAY_TYPE = new StandardDateTimeFieldType( 110 "halfdayOfDay", HALFDAY_OF_DAY, DurationFieldType.halfdays(), DurationFieldType.days()); 111 /** The hourOfHalfday field type. */ 112 private static final DateTimeFieldType HOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType( 113 "hourOfHalfday", HOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays()); 114 /** The clockhourOfHalfday field type. */ 115 private static final DateTimeFieldType CLOCKHOUR_OF_HALFDAY_TYPE = new StandardDateTimeFieldType( 116 "clockhourOfHalfday", CLOCKHOUR_OF_HALFDAY, DurationFieldType.hours(), DurationFieldType.halfdays()); 117 /** The clockhourOfDay field type. */ 118 private static final DateTimeFieldType CLOCKHOUR_OF_DAY_TYPE = new StandardDateTimeFieldType( 119 "clockhourOfDay", CLOCKHOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days()); 120 /** The hourOfDay field type. */ 121 private static final DateTimeFieldType HOUR_OF_DAY_TYPE = new StandardDateTimeFieldType( 122 "hourOfDay", HOUR_OF_DAY, DurationFieldType.hours(), DurationFieldType.days()); 123 /** The minuteOfDay field type. */ 124 private static final DateTimeFieldType MINUTE_OF_DAY_TYPE = new StandardDateTimeFieldType( 125 "minuteOfDay", MINUTE_OF_DAY, DurationFieldType.minutes(), DurationFieldType.days()); 126 /** The minuteOfHour field type. */ 127 private static final DateTimeFieldType MINUTE_OF_HOUR_TYPE = new StandardDateTimeFieldType( 128 "minuteOfHour", MINUTE_OF_HOUR, DurationFieldType.minutes(), DurationFieldType.hours()); 129 /** The secondOfDay field type. */ 130 private static final DateTimeFieldType SECOND_OF_DAY_TYPE = new StandardDateTimeFieldType( 131 "secondOfDay", SECOND_OF_DAY, DurationFieldType.seconds(), DurationFieldType.days()); 132 /** The secondOfMinute field type. */ 133 private static final DateTimeFieldType SECOND_OF_MINUTE_TYPE = new StandardDateTimeFieldType( 134 "secondOfMinute", SECOND_OF_MINUTE, DurationFieldType.seconds(), DurationFieldType.minutes()); 135 /** The millisOfDay field type. */ 136 private static final DateTimeFieldType MILLIS_OF_DAY_TYPE = new StandardDateTimeFieldType( 137 "millisOfDay", MILLIS_OF_DAY, DurationFieldType.millis(), DurationFieldType.days()); 138 /** The millisOfSecond field type. */ 139 private static final DateTimeFieldType MILLIS_OF_SECOND_TYPE = new StandardDateTimeFieldType( 140 "millisOfSecond", MILLIS_OF_SECOND, DurationFieldType.millis(), DurationFieldType.seconds()); 141 142 /** The name of the field. */ 143 private final String iName; 144 145 //----------------------------------------------------------------------- 146 /** 147 * Constructor. 148 * 149 * @param name the name to use 150 */ 151 protected DateTimeFieldType(String name) { 152 super(); 153 iName = name; 154 } 155 156 //----------------------------------------------------------------------- 157 /** 158 * Get the millis of second field type. 159 * 160 * @return the DateTimeFieldType constant 161 */ 162 public static DateTimeFieldType millisOfSecond() { 163 return MILLIS_OF_SECOND_TYPE; 164 } 165 166 /** 167 * Get the millis of day field type. 168 * 169 * @return the DateTimeFieldType constant 170 */ 171 public static DateTimeFieldType millisOfDay() { 172 return MILLIS_OF_DAY_TYPE; 173 } 174 175 /** 176 * Get the second of minute field type. 177 * 178 * @return the DateTimeFieldType constant 179 */ 180 public static DateTimeFieldType secondOfMinute() { 181 return SECOND_OF_MINUTE_TYPE; 182 } 183 184 /** 185 * Get the second of day field type. 186 * 187 * @return the DateTimeFieldType constant 188 */ 189 public static DateTimeFieldType secondOfDay() { 190 return SECOND_OF_DAY_TYPE; 191 } 192 193 /** 194 * Get the minute of hour field type. 195 * 196 * @return the DateTimeFieldType constant 197 */ 198 public static DateTimeFieldType minuteOfHour() { 199 return MINUTE_OF_HOUR_TYPE; 200 } 201 202 /** 203 * Get the minute of day field type. 204 * 205 * @return the DateTimeFieldType constant 206 */ 207 public static DateTimeFieldType minuteOfDay() { 208 return MINUTE_OF_DAY_TYPE; 209 } 210 211 /** 212 * Get the hour of day (0-23) field type. 213 * 214 * @return the DateTimeFieldType constant 215 */ 216 public static DateTimeFieldType hourOfDay() { 217 return HOUR_OF_DAY_TYPE; 218 } 219 220 /** 221 * Get the hour of day (offset to 1-24) field type. 222 * 223 * @return the DateTimeFieldType constant 224 */ 225 public static DateTimeFieldType clockhourOfDay() { 226 return CLOCKHOUR_OF_DAY_TYPE; 227 } 228 229 /** 230 * Get the hour of am/pm (0-11) field type. 231 * 232 * @return the DateTimeFieldType constant 233 */ 234 public static DateTimeFieldType hourOfHalfday() { 235 return HOUR_OF_HALFDAY_TYPE; 236 } 237 238 /** 239 * Get the hour of am/pm (offset to 1-12) field type. 240 * 241 * @return the DateTimeFieldType constant 242 */ 243 public static DateTimeFieldType clockhourOfHalfday() { 244 return CLOCKHOUR_OF_HALFDAY_TYPE; 245 } 246 247 /** 248 * Get the AM(0) PM(1) field type. 249 * 250 * @return the DateTimeFieldType constant 251 */ 252 public static DateTimeFieldType halfdayOfDay() { 253 return HALFDAY_OF_DAY_TYPE; 254 } 255 256 //----------------------------------------------------------------------- 257 /** 258 * Get the day of week field type. 259 * 260 * @return the DateTimeFieldType constant 261 */ 262 public static DateTimeFieldType dayOfWeek() { 263 return DAY_OF_WEEK_TYPE; 264 } 265 266 /** 267 * Get the day of month field type. 268 * 269 * @return the DateTimeFieldType constant 270 */ 271 public static DateTimeFieldType dayOfMonth() { 272 return DAY_OF_MONTH_TYPE; 273 } 274 275 /** 276 * Get the day of year field type. 277 * 278 * @return the DateTimeFieldType constant 279 */ 280 public static DateTimeFieldType dayOfYear() { 281 return DAY_OF_YEAR_TYPE; 282 } 283 284 /** 285 * Get the week of a week based year field type. 286 * 287 * @return the DateTimeFieldType constant 288 */ 289 public static DateTimeFieldType weekOfWeekyear() { 290 return WEEK_OF_WEEKYEAR_TYPE; 291 } 292 293 /** 294 * Get the year of a week based year field type. 295 * 296 * @return the DateTimeFieldType constant 297 */ 298 public static DateTimeFieldType weekyear() { 299 return WEEKYEAR_TYPE; 300 } 301 302 /** 303 * Get the year of a week based year within a century field type. 304 * 305 * @return the DateTimeFieldType constant 306 */ 307 public static DateTimeFieldType weekyearOfCentury() { 308 return WEEKYEAR_OF_CENTURY_TYPE; 309 } 310 311 /** 312 * Get the month of year field type. 313 * 314 * @return the DateTimeFieldType constant 315 */ 316 public static DateTimeFieldType monthOfYear() { 317 return MONTH_OF_YEAR_TYPE; 318 } 319 320 /** 321 * Get the year field type. 322 * 323 * @return the DateTimeFieldType constant 324 */ 325 public static DateTimeFieldType year() { 326 return YEAR_TYPE; 327 } 328 329 /** 330 * Get the year of era field type. 331 * 332 * @return the DateTimeFieldType constant 333 */ 334 public static DateTimeFieldType yearOfEra() { 335 return YEAR_OF_ERA_TYPE; 336 } 337 338 /** 339 * Get the year of century field type. 340 * 341 * @return the DateTimeFieldType constant 342 */ 343 public static DateTimeFieldType yearOfCentury() { 344 return YEAR_OF_CENTURY_TYPE; 345 } 346 347 /** 348 * Get the century of era field type. 349 * 350 * @return the DateTimeFieldType constant 351 */ 352 public static DateTimeFieldType centuryOfEra() { 353 return CENTURY_OF_ERA_TYPE; 354 } 355 356 /** 357 * Get the era field type. 358 * 359 * @return the DateTimeFieldType constant 360 */ 361 public static DateTimeFieldType era() { 362 return ERA_TYPE; 363 } 364 365 //----------------------------------------------------------------------- 366 /** 367 * Get the name of the field. 368 * <p> 369 * By convention, names follow a pattern of "dddOfRrr", where "ddd" represents 370 * the (singular) duration unit field name and "Rrr" represents the (singular) 371 * duration range field name. If the range field is not applicable, then 372 * the name of the field is simply the (singular) duration field name. 373 * 374 * @return field name 375 */ 376 public String getName() { 377 return iName; 378 } 379 380 /** 381 * Get the duration unit of the field. 382 * 383 * @return duration unit of the field, never null 384 */ 385 public abstract DurationFieldType getDurationType(); 386 387 /** 388 * Get the duration range of the field. 389 * 390 * @return duration range of the field, null if unbounded 391 */ 392 public abstract DurationFieldType getRangeDurationType(); 393 394 /** 395 * Gets a suitable field for this type from the given Chronology. 396 * 397 * @param chronology the chronology to use, null means ISOChronology in default zone 398 * @return a suitable field 399 */ 400 public abstract DateTimeField getField(Chronology chronology); 401 402 /** 403 * Checks whether this field supported in the given Chronology. 404 * 405 * @param chronology the chronology to use, null means ISOChronology in default zone 406 * @return true if supported 407 */ 408 public boolean isSupported(Chronology chronology) { 409 return getField(chronology).isSupported(); 410 } 411 412 /** 413 * Get a suitable debug string. 414 * 415 * @return debug string 416 */ 417 public String toString() { 418 return getName(); 419 } 420 421 private static class StandardDateTimeFieldType extends DateTimeFieldType { 422 /** Serialization version */ 423 private static final long serialVersionUID = -9937958251642L; 424 425 /** The ordinal of the standard field type, for switch statements */ 426 private final byte iOrdinal; 427 428 /** The unit duration of the field. */ 429 private final transient DurationFieldType iUnitType; 430 /** The range duration of the field. */ 431 private final transient DurationFieldType iRangeType; 432 433 /** 434 * Constructor. 435 * 436 * @param name the name to use 437 * @param ordinal the byte value for the oridinal index 438 * @param unitType the unit duration type 439 * @param rangeType the range duration type 440 */ 441 StandardDateTimeFieldType(String name, byte ordinal, 442 DurationFieldType unitType, DurationFieldType rangeType) { 443 super(name); 444 iOrdinal = ordinal; 445 iUnitType = unitType; 446 iRangeType = rangeType; 447 } 448 449 /** @inheritdoc */ 450 public DurationFieldType getDurationType() { 451 return iUnitType; 452 } 453 454 /** @inheritdoc */ 455 public DurationFieldType getRangeDurationType() { 456 return iRangeType; 457 } 458 459 /** @inheritdoc */ 460 public DateTimeField getField(Chronology chronology) { 461 chronology = DateTimeUtils.getChronology(chronology); 462 463 switch (iOrdinal) { 464 case ERA: 465 return chronology.era(); 466 case YEAR_OF_ERA: 467 return chronology.yearOfEra(); 468 case CENTURY_OF_ERA: 469 return chronology.centuryOfEra(); 470 case YEAR_OF_CENTURY: 471 return chronology.yearOfCentury(); 472 case YEAR: 473 return chronology.year(); 474 case DAY_OF_YEAR: 475 return chronology.dayOfYear(); 476 case MONTH_OF_YEAR: 477 return chronology.monthOfYear(); 478 case DAY_OF_MONTH: 479 return chronology.dayOfMonth(); 480 case WEEKYEAR_OF_CENTURY: 481 return chronology.weekyearOfCentury(); 482 case WEEKYEAR: 483 return chronology.weekyear(); 484 case WEEK_OF_WEEKYEAR: 485 return chronology.weekOfWeekyear(); 486 case DAY_OF_WEEK: 487 return chronology.dayOfWeek(); 488 case HALFDAY_OF_DAY: 489 return chronology.halfdayOfDay(); 490 case HOUR_OF_HALFDAY: 491 return chronology.hourOfHalfday(); 492 case CLOCKHOUR_OF_HALFDAY: 493 return chronology.clockhourOfHalfday(); 494 case CLOCKHOUR_OF_DAY: 495 return chronology.clockhourOfDay(); 496 case HOUR_OF_DAY: 497 return chronology.hourOfDay(); 498 case MINUTE_OF_DAY: 499 return chronology.minuteOfDay(); 500 case MINUTE_OF_HOUR: 501 return chronology.minuteOfHour(); 502 case SECOND_OF_DAY: 503 return chronology.secondOfDay(); 504 case SECOND_OF_MINUTE: 505 return chronology.secondOfMinute(); 506 case MILLIS_OF_DAY: 507 return chronology.millisOfDay(); 508 case MILLIS_OF_SECOND: 509 return chronology.millisOfSecond(); 510 default: 511 // Shouldn't happen. 512 throw new InternalError(); 513 } 514 } 515 516 /** 517 * Ensure a singleton is returned. 518 * 519 * @return the singleton type 520 */ 521 private Object readResolve() { 522 switch (iOrdinal) { 523 case ERA: 524 return ERA_TYPE; 525 case YEAR_OF_ERA: 526 return YEAR_OF_ERA_TYPE; 527 case CENTURY_OF_ERA: 528 return CENTURY_OF_ERA_TYPE; 529 case YEAR_OF_CENTURY: 530 return YEAR_OF_CENTURY_TYPE; 531 case YEAR: 532 return YEAR_TYPE; 533 case DAY_OF_YEAR: 534 return DAY_OF_YEAR_TYPE; 535 case MONTH_OF_YEAR: 536 return MONTH_OF_YEAR_TYPE; 537 case DAY_OF_MONTH: 538 return DAY_OF_MONTH_TYPE; 539 case WEEKYEAR_OF_CENTURY: 540 return WEEKYEAR_OF_CENTURY_TYPE; 541 case WEEKYEAR: 542 return WEEKYEAR_TYPE; 543 case WEEK_OF_WEEKYEAR: 544 return WEEK_OF_WEEKYEAR_TYPE; 545 case DAY_OF_WEEK: 546 return DAY_OF_WEEK_TYPE; 547 case HALFDAY_OF_DAY: 548 return HALFDAY_OF_DAY_TYPE; 549 case HOUR_OF_HALFDAY: 550 return HOUR_OF_HALFDAY_TYPE; 551 case CLOCKHOUR_OF_HALFDAY: 552 return CLOCKHOUR_OF_HALFDAY_TYPE; 553 case CLOCKHOUR_OF_DAY: 554 return CLOCKHOUR_OF_DAY_TYPE; 555 case HOUR_OF_DAY: 556 return HOUR_OF_DAY_TYPE; 557 case MINUTE_OF_DAY: 558 return MINUTE_OF_DAY_TYPE; 559 case MINUTE_OF_HOUR: 560 return MINUTE_OF_HOUR_TYPE; 561 case SECOND_OF_DAY: 562 return SECOND_OF_DAY_TYPE; 563 case SECOND_OF_MINUTE: 564 return SECOND_OF_MINUTE_TYPE; 565 case MILLIS_OF_DAY: 566 return MILLIS_OF_DAY_TYPE; 567 case MILLIS_OF_SECOND: 568 return MILLIS_OF_SECOND_TYPE; 569 default: 570 // Shouldn't happen. 571 return this; 572 } 573 } 574 } 575 576 }